#!/USR/BIn/env python
'''
Coasters handler
'''

import gobject
import gtk
import Gui
import Brands
import Breweries
import Img
import os
from DB import DB
from GladeWidgets import GladeWidget

class Coaster:
    '''Some constraints useful for the model'''
    ID          = 0
    BRAND       = 1
    IMG_FRONT   = 2
    IMG_BACK    = 3

def on_btnCoasterAdd_clicked(wnd, event):
    '''Add a new coaster'''
    wndCoastersAdd = GladeWidget("wndAddCoaster")

    _setupComboBrand(wndCoastersAdd["comboBrand"])
    _setupFileChooser(wndCoastersAdd)
    
    res = False
    while (res == False):
        ret = wndCoastersAdd["wndAddCoaster"].run()

        if (ret == 1): # cancel
            res = True
        elif (ret == 2): # add
            res = _addCoaster(wndCoastersAdd)
            if (res == True):
                Breweries.showTreeview(wnd["treeviewBreweries"])
                Brands.showTreeview(wnd["treeviewBrands"])
                showTreeview(wnd["treeviewCoasters"])

    wndCoastersAdd["wndAddCoaster"].destroy()

def on_btnCoasterEdit_clicked(wnd, event):
    '''Edit an existing coaster'''
    wndCoastersEdit = GladeWidget("wndEditCoaster")

    if (_setupEditWindow(wnd, wndCoastersEdit) == False):
        return False
    
    model, iterator = wnd["treeviewCoasters"].get_selection().get_selected()
    oldid = model.get_value(iterator, Coaster.ID)

    _setupFileChooser(wndCoastersEdit)

    res = False
    while (res == False):
        ret = wndCoastersEdit["wndEditCoaster"].run()
        if (ret == 1): # cancel
            res = True
        elif (ret == 2):
            res = _editCoaster(wndCoastersEdit, oldid)
            if (res == True):
                showTreeview(wnd["treeviewCoasters"])
                Brands.showTreeview(wnd["treeviewBrands"])
                Breweries.showTreeview(wnd["treeviewBreweries"])
    wndCoastersEdit["wndEditCoaster"].destroy()

def on_btnCoasterDel_clicked(wnd, event):
    '''Delete a coaster'''
    model, iterator = wnd["treeviewCoasters"].get_selection().get_selected()
    if not iterator:
        Gui.ErrorBox(str="Select an item to delete first!")
    else:
        yesno = gtk.MessageDialog(wnd["wndMain"], gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
                " Do you want to delete this coaster?")

        def delCoasterResponse(window, response_id):
            if response_id == gtk.RESPONSE_YES:
                path = wnd["treeviewCoasters"].get_model().get_path(iterator)[Coaster.ID]
                db = DB()
                db.delCoaster(model.get_value(iterator, Coaster.ID))
                wnd["treeviewCoasters"].get_model().remove(iterator)
                Brands.showTreeview(wnd["treeviewBrands"])
                Breweries.showTreeview(wnd["treeviewBreweries"])
            yesno.destroy()

        yesno.connect("response", delCoasterResponse)
        yesno.show()

def on_btnDetails_clicked(wnd, event):
    '''Show details about a coaster'''
    wndInfo = GladeWidget("wndCoasterDetails")
    model, iterator = wnd["treeviewCoasters"].get_selection().get_selected()

    if not iterator:
        Gui.ErrorBox(str="Select an item to display first!")
        return False

    id = model.get_value(iterator, Coaster.ID)

    _setInfoWindow(wndInfo, id)
    wndInfo["wndCoasterDetails"].show()


def setTreeModel(wnd):
    '''Setup the model for the brand tree view'''
    treeview = wnd["treeviewCoasters"]
    model = gtk.ListStore(  gobject.TYPE_INT,    # coaster id
                            gobject.TYPE_STRING, # coaster brand
                            gtk.gdk.Pixbuf,      # coaster front
                            gtk.gdk.Pixbuf)      # coaster back

    treeview.set_model(model)

    # setup the cells
    Gui.treeviewAddGeneralTextColumn(treeview, "ID", Coaster.ID, resizable=False, reorderable=True)
    Gui.treeviewAddGeneralTextColumn(treeview, "Brand name", Coaster.BRAND, resizable=True, reorderable=True)
    Gui.treeviewAddGeneralPixbufColumn(treeview, "Front", Coaster.IMG_FRONT, resizable=False, reorderable=False)
    Gui.treeviewAddGeneralPixbufColumn(treeview, "Back", Coaster.IMG_BACK, resizable=False, reorderable=False)

    showTreeview(treeview)

def showTreeview(treeview, filter='%'):
    '''Show the coaster's treeview'''
    db = DB()
    coasters = db.getAllCoasters(filter)
    treeview.get_model().clear()
    for id, name in coasters:
        _addRow(treeview, id, name, db.getFrontCoasterImg(id), db.getBackCoasterImg(id))

def _setupComboBrand(combo, the_active=None):
    '''Add the brands to the combobox'''
    db = DB()
    brands = db.getAllBrands()
    # transform set in list
    list = []
    for brand in brands:
        list.append(brand[0])
    Gui.setCombobox(combo, list, has_na=False, active=the_active)

def _setupFileChooser(wnd):
    wnd["btnFileChooserFront"].add_filter(Gui.setImageFilter())
    wnd["btnFileChooserBack"].add_filter(Gui.setImageFilter())
    previewFront = gtk.Image()
    previewBack = gtk.Image()
    wnd["btnFileChooserFront"].set_preview_widget(previewFront)
    wnd["btnFileChooserBack"].set_preview_widget(previewBack)

    wnd["btnFileChooserFront"].connect("update-preview", _fileChooserPreview, previewFront)
    wnd["btnFileChooserBack"].connect("update-preview", _fileChooserPreview, previewBack)

def _fileChooserPreview(filec, preview):
    '''Set up the file chooser preview property'''
    filename = filec.get_preview_filename()
    try:
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename, 150, 150)
        preview.set_from_pixbuf(pixbuf)
        have_preview = True
    except:
        have_preview = False
    filec.set_preview_widget_active(have_preview)
    return

def _addCoaster(wnd):
    '''Add a new coaster to the db'''
    brand = wnd["comboBrand"].get_active_text()
    comment = wnd["txtComments"].get_text()
    front = wnd["btnFileChooserFront"].get_filename()
    back = wnd["btnFileChooserBack"].get_filename()

    if ((brand == None) or (len(brand) == 0)):
        Gui.ErrorBox(str="Please insert all the required fields (a brand name is required)")
        return False

    if ((front == None) or (len(front) == 0)):
        Gui.ErrorBox(str="Please insert all the required fields (a front coaster photo is required)")
        return False

    if ((back == None) or (len(back) == 0)):
        back = None

    front, newfile_front = Img.resizeFile(front, 330)
    if (back != None):
        back, newfile_back = Img.resizeFile(back, 330)

    db = DB()
    db.addCoaster(brand, front, back, comment)

    if ((front != None) and (newfile_front == True)):
        os.remove(front)
    if ((back != None) and (newfile_back == True)):
        os.remove(back)

    return True
    

def _addRow(treeview, id, name, front_img = None, back_img = None):
    '''Add a new item to the treeview'''
    model = treeview.get_model()
    item = model.append(None)
    model.set_value(item, Coaster.ID, int(id))
    model.set_value(item, Coaster.BRAND, name)

    if (front_img != None):
        front_img = Img.scale_stream(front_img, height=60)
    if (back_img != None):
        back_img = Img.scale_stream(back_img, height=60)

    model.set_value(item, Coaster.IMG_FRONT, front_img)
    model.set_value(item, Coaster.IMG_BACK, back_img)

def _setupEditWindow(wndMain, wndEdit):
    model, iterator = wndMain["treeviewCoasters"].get_selection().get_selected()
    if (not iterator):
        Gui.ErrorBox(str="Select an item to edit first!")
        return False

    db = DB()
    id = model.get_value(iterator, Coaster.ID)
    comment = db.getCoasterComment(id)
    if (comment == None):
        comment = ""

    wndEdit["txtComments"].set_text(comment)
    active_brand = model.get_value(iterator, Coaster.BRAND)

    _setupComboBrand(wndEdit["comboBrand"], the_active=active_brand)
    return True

def _editCoaster(wnd, oldid):
    brand = wnd["comboBrand"].get_active_text()
    comment = wnd["txtComments"].get_text()
    front_image = wnd["btnFileChooserFront"].get_filename()
    back_image = wnd["btnFileChooserBack"].get_filename()

    if ((brand == None) or (len(brand) == 0)):
        Gui.ErrorBox(str="Please insert all the required fields (a brand name is required)")
        return False

    if (comment == None):
        comment = ""

    if (front_image != None):
        front_image, newfile_front = Img.resizeFile(front_image, 330)
    if (back_image != None):
        back_image, newfile_back = Img.resizeFile(back_image, 330)

    db = DB()
    db.updateCoaster(oldid, brand, front_image, back_image, comment)

    if ((front_image != None) and (newfile_front == True)):
        os.remove(front_image)
    if ((back_image != None) and (newfile_back == True)):
        os.remove(back_image)

    return True

def _setInfoWindow(w, id):
    '''Setup the details'window'''
    db = DB()
    brand = db.getCoasterBrand(id)
    brand_comment = db.getBrandComment(brand)
    brand_country = db.getBrandCountry(brand)
    coaster_comment = db.getCoasterComment(id)

    if (brand_comment == None):
        brand_comment = ""
    if (coaster_comment == None):
        coaster_comment = ""

    w["lblBrand"].set_use_markup(True)
    w["lblBrand"].set_label("<big><b>" + brand  + ", " + brand_country + "</b></big>")

    w["txtBrandComment"].set_text(brand_comment)
    w["txtCoasterComment"].set_text(coaster_comment)

    w["imgFront"].set_from_pixbuf(Img.convertRawStreamToPixbuf(db.getFrontCoasterImg(id)))
    w["imgBack"].set_from_pixbuf(Img.convertRawStreamToPixbuf(db.getBackCoasterImg(id)))

    w.widgets.signal_connect("on_btnOk_clicked", lambda x: w["wndCoasterDetails"].destroy())
